/*
 * Copyright (c) 2018, ZeeSec Technologies. All rights reserved.
 * ZeeSec PROPRIETARY/CONFIDENTIAL.
 */

package springtest.httpClient;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author ZhiQiang Chen
 * @date 2018-09-10 17:23:02
 */

public class HttpClientUtils {

    private static final Logger log = LoggerFactory.getLogger(HttpClientUtils.class);
    public static CloseableHttpClient httpClient = null;
    public static HttpClientContext context = null;
    public static CookieStore cookieStore = null;
    public static RequestConfig requestConfig = null;

    static {
        try {
            init();
        } catch (Exception e) {
            log.error("httpClient初始化失败", e);
        }
    }

    public static void init() throws Exception {
        context = HttpClientContext.create();
        cookieStore = new BasicCookieStore();
        // 配置超时时间（连接服务端超时1秒，请求数据返回超时2秒）
        requestConfig = RequestConfig.custom().setConnectTimeout(120000).setSocketTimeout(60000)
                .setConnectionRequestTimeout(60000).setCookieSpec(CookieSpecs.STANDARD).build();

        ConnectionKeepAliveStrategy connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) {
                return 20 * 1000; // 20 seconds,because tomcat default
                                  // keep-alive timeout is 20s
            }
        };
        // 设置默认跳转以及存储cookie
        httpClient = HttpClientBuilder.create().setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
                .setRedirectStrategy(new DefaultRedirectStrategy()).setDefaultRequestConfig(requestConfig)
                .setDefaultCookieStore(cookieStore).setSSLSocketFactory(buildSSLConnectionSocketFactory())
                .setKeepAliveStrategy(connectionKeepAliveStrategy).build();
    }

    public static String getPhpSesssionId() {
        List<Cookie> cookies = cookieStore.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println("key:" + cookie.getName() + "  value:" + cookie.getValue());
            if (cookie.getName().equals("PHPSESSID")) {
                return cookie.getValue();
            }
        }
        return null;
    }

    public static String getSessionIdMd5By3() {
        List<Cookie> cookies = cookieStore.getCookies();
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("SESSID")) {
                // System.out.println("key:" + cookie.getName() + " value:" +
                // cookie.getValue());
                return DigestUtils.md5Hex(DigestUtils.md5Hex(DigestUtils.md5Hex(cookie.getValue())));
            }
        }
        return null;
    }

    public static void addCookie(String name, String value, String domain, String path) {
        BasicClientCookie cookie = new BasicClientCookie(name, value);
        cookie.setDomain(domain);
        cookie.setPath(path);
        cookieStore.addCookie(cookie);
    }

    /**
     * 把当前cookie从控制台输出出来
     * 
     */
    public static void printCookies() {
        // cookieStore = context.getCookieStore();
        // if (cookieStore != null) {
        List<Cookie> cookies = cookieStore.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println("key:" + cookie.getName() + " value:" + cookie.getValue());
            // }
        }
    }

    public static CloseableHttpClient getHttpClient() {
        return httpClient;
    }

    public static HttpClientContext getContext() {
        return context;
    }

    public static CookieStore getCookieStore() {
        return cookieStore;
    }

    public static RequestConfig getRequestConfig() {
        return requestConfig;
    }

    public static void setRequestConfig(RequestConfig requestConfig) {
        HttpClientUtils.requestConfig = requestConfig;
    }

    /*
     * 忽略https验证
     */
    @SuppressWarnings({ "deprecation", "unused" })
    private static SSLConnectionSocketFactory buildSSLConnectionSocketFactory() throws Exception {
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            // 信任所有
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        }).build();
        // ALLOW_ALL_HOSTNAME_VERIFIER:这个主机名验证器基本上是关闭主机名验证的,实现的是一个空操作，并且不会抛出javax.net.ssl.SSLException异常。
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1" }, null,
                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return sslsf;
    }
}
